#include "skynet.h"
#include "skynet_env.h"
#include "spinlock.h"

#include <lua.h>
#include <lauxlib.h>

#include <stdlib.h>
#include <assert.h>

struct skynet_env {
	struct spinlock lock;
	lua_State *L;
};

static struct skynet_env *E = NULL;

const char * 
skynet_getenv(const char *key) {
	SPIN_LOCK(E)

	lua_State *L = E->L;
	lua_getglobal(L, key); //将lua虚拟机中名字为key的全局变量的值，压入到lua堆栈的栈顶
	const char * result = lua_tostring(L, -1); //将堆栈中自顶向下的第一个元素转化为C字符串
	lua_pop(L, 1); //堆栈从栈顶开始, 弹出1个元素

	SPIN_UNLOCK(E)

	return result;
}

void 
skynet_setenv(const char *key, const char *value) {
	SPIN_LOCK(E)
	
	lua_State *L = E->L;
	lua_getglobal(L, key); //将lua虚拟机中名字为key的全局变量的值，压入到lua堆栈的栈顶
	assert(lua_isnil(L, -1)); //断言当前堆栈栈顶的元素为nil，即要求原先lua虚拟机中名字为key的全局变量 = nil
	lua_pop(L,1); //自栈顶开始弹出1个元素, 即先前压入的nil
	lua_pushstring(L,value); //将字符串value压入堆栈
	lua_setglobal(L,key); //弹出堆栈栈顶的值, 即value, 并将其作为lua虚拟机中名字为key的全局变量的新值

	SPIN_UNLOCK(E)
}

void
skynet_env_init() {
	E = skynet_malloc(sizeof(*E));
	SPIN_INIT(E)
	E->L = luaL_newstate(); //创建一个新的lua状态机
}
